package cn.maihe.elg.operation.supports.invoice.nuonuo.dto;

import cn.maihe.elg.operation.repository.entity.InvoiceInfoDO;
import cn.maihe.elg.operation.repository.entity.SellerInfoDO;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description
 * @Author caixh
 * @Date 2021/4/30.
 */
@Data
public class OrderDTO {
    /**
     * 购方名称  100 必输
     */
    private String buyerName;
    /**
     * 购方税号（企业要填，个人可为空） 20
     */
    private String buyerTaxNum;
    /**
     * 购方电话 20
     */
    private String buyerTel;
    /**
     * 购方地址 80
     */
    private String buyerAddress;

    /**
     * 购方银行账号及开户行地址 100
     */
    private String buyerAccount;

    /**
     * 销方税号（使用沙箱环境请求时消息体参
     * 数salerTaxNum和消息头参数userTax
     * 填写339901999999142） 20 必输
     */
    private String salerTaxNum;
    /**
     * 销方电话 20 必输
     */
    private String salerTel;
    /**
     * 销方地址 80 必输
     */
    private String salerAddress;
    /**
     * 销方银行账号和开户行地址 100
     */
    private String salerAccount;
    /**
     * 订单号（每个企业唯一） 20 必输
     */
    private String orderNo;

    /**
     * 订单时间 20 必输
     * 2016-01-13 12:30:00
     */
    private String invoiceDate;
    /**
     * 冲红时填写的对应蓝票发票代码（红票必
     * 填，不满12位请左补0） 12
     */
    private String invoiceCode;

    /**
     * 冲红时填写的对应蓝票发票号码（红票必
     * 填，不满8位请左补0） 8
     */
    private String invoiceNum;
    /**
     * 冲红原因：1:销货退回;2:开票有误;3:服务中止;4:发生销售折让(开具红票时且票种为p,c,e,f,r需要传--成品油发票除外；不传时默认为 1)
     */
    private String redReason;


    /**
     * 红字信息表编号.专票冲红时此项必填，且
     * 必须在备注中注明“开具红字增值税专用
     * 发票信息表编号ZZZZZZZZZZZZZZZ
     * Z”字样，其 中“Z”为开具红字增值税专
     * 用发票所需要的长度为16位信息表编号。 16
     */
    private String billInfoNo;

    /**
     * 部门门店id（诺诺系统中的id） 32
     */
    private String departmentId;
    /**
     * 开票员id 32
     */
    private String clerkId;
    /**
     * 备注信息 230 冲红时，在备注中注明“对应正数发票代码:XXXXXXXXX号码:YYYYYYYY”文案，其中“X”为发票代码，“Y”为发票号码，可以不填，接口会自动添加该文案；机动车发票蓝票时备注只能为空；数电票时最长为200字符
     */
    private String remark;
    /**
     * 复核人 20
     */
    private String checker;
    /**
     * 收款人 20
     */
    private String payee;
    /**
     * 开票员  20 必输
     */
    private String clerk;
    /**
     * 清单标志：非清单:0；清单:1，默认:0  1
     */
    private String listFlag;
    /**
     * 清单项目名称：对应发票票面项目名称（li
     * stFlag为1时，必填，默认为“详见销货清
     * 单”）  92
     */
    private String listName;
    /**
     * 推送方式：-1,不推送;0,邮箱;1,手机（默认
     * ）;2,邮箱、手机 2
     */
    private String pushMode;
    /**
     * 购方手机（pushMode为1或2时，此项为
     * 必填）  20 必输
     */
    private String buyerPhone;

    /**
     * 推送邮箱（pushMode为0或2时，此项为
     * 必填） 50 必输
     */
    private String email;

    /**
     * 开票类型：1:蓝票;2:红票 1 必输
     */
    private String invoiceType;
    /**
     * 发票种类：p,普通发票(电票)(默认);c,普通发票(纸票);s,专用发票;e,收购发票(电票);f,收购发票(纸质);r,普通发票(卷式);
     * b,增值税电子专用发票;j,机动车销售统一发票;u,二手车销售统一发票;
     * bs:电子发票(增值税专用发票)-即数电专票(电子),pc:电子发票(普通发票)-即数电普票(电子),
     * es:数电纸质发票(增值税专用发票)-即数电专票(纸质);ec:数电纸质发票(普通发票)-即数电普票(纸质)
     * es:数电纸质发票(增值税专用发票)-即数电专票(纸质);ec:数电纸质发票(普通发票)-即数电普票(纸质)
     */
    private String invoiceLine;
    /**
     * 数电纸票类型(数电纸票时才需要传)：（票种为ec时，默认04；票种为es时，默认为1130）; 04 2016版增值税普通发票（二联折叠票）, 05 2016版增值税普通发票（五联折叠票), 1130 增值税专用发票（中文三联无金额限制版）, 1140 增值税专用发票（中文四联无金额限制版）, 1160 增值税专用发票（中文六联无金额限制版）, 1170 增值税专用发票（中文七联无金额限制版）
     */
    private String paperInvoiceType;
    /**
     * 特定要素：0普通发票（默认）、1 成品油 、3 建筑服务、4 货物运输服务、5 不动产销售、6 不动产经营租赁服务、9 旅客运输服务、16 农产品收购、31 建安发票 、 32 房地产销售发票、33 二手车发票反向开具、 34 电子烟、 35 矿产品
     */
    private String specificFactor;
    /**
     * 是否强制开具标识：0 否、1 是 （发票种类为u，且特定要素为 33-二手车发票反向开具时才需要填； 默认为 0；若为1时，则不校验卖方自然人身份证号的合规性）
     */
    private String forceFlag;
    /**
     * 代开标志：0非代开;1代开。代开蓝票时备
     * 注要求填写文案：代开企业税号:***,代开企
     * 业名称:***；代开红票时备注要求填写文案
     * ：对应正数发票代码:***号码:***代开企业
     * 税号:***代开企业名称:*** 1
     */
    private String proxyInvoiceFlag;

    /**
     * 代办退税标记：0否（默认），1是；仅代办退税资质企业可传1
     */
    private String taxRebateProxy;

    /**
     * 数电发票差额征税开具方式：01 全额开票（暂不支持），02 差额开票；非数电发票开具差额时，不传
     */
    private String invoiceDifferenceType;

    /**
     * 开票完成回传发票信息地址
     */
    private String callBackUrl;
    /**
     * 分机号（只能为空或者数字）  5
     */
    private String extensionNumber;
    /**
     * 终端号（开票终端号，只能 为空或数字）  4
     */
    private String terminalNumber;
    /**
     * 开票员发票明细，支持填写商品明细最大   必输
     */
    private List<InvoiceDetail> invoiceDetail;

    public OrderDTO(InvoiceInfoDO invoiceInfoDO, SellerInfoDO sellerInfoDO, String callBackUrl, boolean isReversal, String extensionNumber, String remark) {
        buyerName = invoiceInfoDO.getCustomerName();
        buyerTaxNum = invoiceInfoDO.getCustomerCreditCode();
        buyerTel = invoiceInfoDO.getCustomerPhone();
        buyerAddress = invoiceInfoDO.getCustomerAddress();
        String customerOpenBank = StringUtils.isEmpty(invoiceInfoDO.getCustomerOpneBank()) ? "" : invoiceInfoDO.getCustomerOpneBank().trim();
        String customerBankCode = StringUtils.isEmpty(invoiceInfoDO.getCustomerBankCode()) ? "" : invoiceInfoDO.getCustomerBankCode().trim();
        buyerAccount = customerOpenBank + " " + customerBankCode;
        this.extensionNumber = extensionNumber;
        salerTaxNum = invoiceInfoDO.getSellerCreditCode();
        salerTel = invoiceInfoDO.getSellerPhone();
        salerAddress = invoiceInfoDO.getSellerAddress();
        salerAccount = StringUtils.isEmpty(invoiceInfoDO.getSellerOpenBank()) ? "" : (
                invoiceInfoDO.getSellerOpenBank() + " " + invoiceInfoDO.getSellerBankCode());
        orderNo = invoiceInfoDO.getId().toString();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        invoiceDate = sdf.format(invoiceInfoDO.getGmtCreate());
        this.remark = StringUtils.isEmpty(remark) ? sellerInfoDO.getInvoiceRemark() : remark;
        checker = sellerInfoDO.getChecker();
        payee = sellerInfoDO.getPayee();
        clerk = invoiceInfoDO.getHandler();
        if (StringUtils.isEmpty(invoiceInfoDO.getCustomerContactEamil())) {
            if (StringUtils.isEmpty(invoiceInfoDO.getCustomerContactTel())) {
                pushMode = "-1";
            } else {
                pushMode = "1";
                buyerPhone = invoiceInfoDO.getCustomerContactTel();
            }
        } else if (StringUtils.isEmpty(invoiceInfoDO.getCustomerContactTel())) {
            email = invoiceInfoDO.getCustomerContactEamil();
            pushMode = "0";
        } else {
            email = invoiceInfoDO.getCustomerContactEamil();
            buyerPhone = invoiceInfoDO.getCustomerContactTel();
            pushMode = "2";
        }
        invoiceType = "1";
        if (StringUtils.isNotBlank(invoiceInfoDO.getInvoiceLine())) {
            invoiceLine = invoiceInfoDO.getInvoiceLine();
        } else {
            invoiceLine = "pc";
        }
        this.callBackUrl = callBackUrl;
        invoiceDetail = new ArrayList<>();
        InvoiceDetail detail = new InvoiceDetail();
        detail.setGoodsName("*金融服务*保函费");
        detail.setWithTaxFlag("0");

        BigDecimal amount = new BigDecimal(invoiceInfoDO.getAmount()).divide(new BigDecimal("100"));
        BigDecimal taxRate = new BigDecimal(sellerInfoDO.getRate()).divide(new BigDecimal("100"));
        BigDecimal taxExcludedAmount = amount.divide(taxRate.add(BigDecimal.ONE), 2, RoundingMode.HALF_UP);
        BigDecimal tax = amount.multiply(taxRate).divide(taxRate.add(BigDecimal.ONE), 2, RoundingMode.HALF_UP);

        detail.setPrice(taxExcludedAmount.toString());
        detail.setNum("1");
        detail.setUnit("笔");
        detail.setTax(tax.toString());
        detail.setTaxRate(taxRate.toString());
        detail.setTaxExcludedAmount(taxExcludedAmount.toString());
        detail.setTaxIncludedAmount(amount.toString());

        //若为冲红标识，则按需重置冲红相关信息
        if (isReversal) {
            invoiceCode = invoiceInfoDO.getInvoiceCode();
            invoiceNum = invoiceInfoDO.getInvoiceNo();
            remark = null;
            invoiceType = "2";
            detail.setNum("-1");
            detail.setTax("-" + tax.toString());
            detail.setTaxExcludedAmount("-" + taxExcludedAmount.toString());
            detail.setTaxIncludedAmount("-" + amount.toString());
        }

        invoiceDetail.add(detail);
    }

}
